home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / dflat8.zip / DIALBOX.C < prev    next >
Text File  |  1991-09-30  |  20KB  |  865 lines

  1. /* ----------------- dialbox.c -------------- */
  2.  
  3. #include "dflat.h"
  4.  
  5. static char path[MAXPATH];
  6. static char drive[MAXDRIVE] = " :";
  7. static char dir[MAXDIR];
  8. static char name[MAXFILE];
  9. static char ext[MAXEXT];
  10.  
  11. static int inFocusCommand(DBOX *);
  12. static void dbShortcutKeys(DBOX *, int);
  13. static int ControlProc(WINDOW, MESSAGE, PARAM, PARAM);
  14. static void ChangeFocus(WINDOW, int);
  15. static CTLWINDOW *AssociatedControl(DBOX *, enum commands);
  16. static void SetRadioButton(DBOX *, CTLWINDOW *);
  17.  
  18. static int SysMenuOpen;
  19.  
  20. int DialogProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  21. {
  22.     DBOX *db = wnd->extension;
  23.     CTLWINDOW *ct;
  24.     WINDOW cwnd;
  25.     int rtn;
  26.  
  27.     switch (msg)    {
  28.         case CREATE_WINDOW:
  29.             rtn = BaseWndProc(DIALOG, wnd, msg, p1, p2);
  30.             ct = db->ctl;
  31.             while (ct->class)    {
  32.                 int attrib = VISIBLE;
  33.                 if (TestAttribute(wnd, NOCLIP))
  34.                     attrib |= NOCLIP;
  35.                 if (wnd->Modal)
  36.                     attrib |= SAVESELF;
  37.                 ct->vtext = ct->itext;
  38.                 ct->setting = ct->isetting;
  39.                 if (ct->class == EDITBOX && ct->dwnd.h > 1)
  40.                     attrib |= (MULTILINE | HASBORDER);
  41.                 else if (ct->class == LISTBOX || ct->class == TEXTBOX)
  42.                     attrib |= HASBORDER;
  43.                 cwnd = CreateWindow(ct->class,
  44.                              ct->dwnd.title,
  45.                              ct->dwnd.x+GetClientLeft(wnd),
  46.                              ct->dwnd.y+GetClientTop(wnd),
  47.                              ct->dwnd.h,
  48.                              ct->dwnd.w,
  49.                              ct,
  50.                              wnd,
  51.                              ControlProc,
  52.                              attrib);
  53.                 if ((ct->class == EDITBOX || ct->class == COMBOBOX) &&
  54.                         ct->itext != NULL)
  55.                     SendMessage(cwnd, EB_PUTTEXT, (PARAM) ct->itext, 0);
  56.                 if (ct->class != BOX &&
  57.                     ct->class != TEXT &&
  58.                         wnd->dFocus == NULL)
  59.                     wnd->dFocus = ct;
  60.                 ct++;
  61.             }
  62.             return rtn;
  63.         case SETFOCUS:
  64.             if (wnd->Modal)    {
  65.                 if (p1)
  66.                     SendMessage(inFocus, SETFOCUS, FALSE, 0);
  67.                 inFocus = p1 ? wnd : NULL;
  68.                 return TRUE;
  69.             }
  70.             break;
  71.         case SHIFT_CHANGED:
  72.             if (wnd->Modal)
  73.                 return TRUE;
  74.             break;
  75.         case LEFT_BUTTON:
  76.             if (WindowSizing || WindowMoving)
  77.                 return FALSE;
  78.             if (HitControlBox(wnd, p1-GetLeft(wnd), p2-GetTop(wnd)))    {
  79.                 PostMessage(wnd, KEYBOARD, ' ', ALTKEY);
  80.                 return TRUE;
  81.             }
  82.             ct = db->ctl;
  83.             while (ct->class)    {
  84.                 WINDOW cwnd = ct->wnd;
  85.                 if (ct->class == COMBOBOX)    {
  86.                     if (p2 == GetTop(cwnd))    {
  87.                         if (p1 == GetRight(cwnd)+1)    {
  88.                             SendMessage(cwnd, msg, p1, p2);
  89.                             return TRUE;
  90.                         }
  91.                     }
  92.                     if (GetClass(inFocus) == LISTBOX)
  93.                         SendMessage(wnd, SETFOCUS, TRUE, 0);
  94.                 }
  95.                 else if (ct->class == SPINBUTTON)    {
  96.                     if (p2 == GetTop(cwnd))    {
  97.                         if (p1 == GetRight(cwnd)+1 ||
  98.                                 p1 == GetRight(cwnd)+2)    {
  99.                             SendMessage(cwnd, msg, p1, p2);
  100.                             return TRUE;
  101.                         }
  102.                     }
  103.                 }
  104.                 ct++;
  105.             }
  106.             break;
  107.         case KEYBOARD:
  108.             if (WindowMoving || WindowSizing)
  109.                 break;
  110.             switch ((int)p1)    {
  111.                 case F1:
  112.                     ct = wnd->dFocus;
  113.                     if (ct != NULL)
  114.                         if (DisplayHelp(wnd, ct->help))
  115.                             return TRUE;
  116.                     break;
  117.                 case CTRL_FIVE:        /* same as SHIFT-TAB */
  118.                     if ((int)p2 & (LEFTSHIFT | RIGHTSHIFT))
  119.                         ChangeFocus(wnd, FALSE);
  120.                     break;
  121.                 case BS:
  122.                 case UP:
  123.                     ChangeFocus(wnd, FALSE);
  124.                     break;
  125.                 case ALT_F6:
  126.                 case '\t':
  127.                 case FWD:
  128.                 case DN:
  129.                     ChangeFocus(wnd, TRUE);
  130.                     break;
  131.                 case ' ':
  132.                     if (((int)p2 & ALTKEY) && TestAttribute(wnd, CONTROLBOX))    {
  133.                         SysMenuOpen = TRUE;
  134.                         BuildSystemMenu(wnd);
  135.                     }
  136.                     break;
  137.                 case CTRL_F4:
  138.                 case ESC:
  139.                     SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  140.                     break;
  141.                 default:
  142.                     /* ------ search all the shortcut keys ----- */
  143.                     dbShortcutKeys(db, (int) p1);
  144.                     break;
  145.             }
  146.             if (wnd->Modal)
  147.                 return TRUE;
  148.             break;
  149.         case CLOSE_POPDOWN:
  150.             SysMenuOpen = FALSE;
  151.             break;
  152.         case LB_SELECTION:
  153.         case LB_CHOOSE:
  154.             if (SysMenuOpen)
  155.                 return TRUE;
  156.             SendMessage(wnd, COMMAND, inFocusCommand(db), msg);
  157.             break;
  158.         case COMMAND:
  159.             switch ((int) p1)    {
  160.                 case ID_OK:
  161.                 case ID_CANCEL:
  162.                     if ((int)p2 != 0)
  163.                         return TRUE;
  164.                     wnd->ReturnCode = (int) p1;
  165.                     if (wnd->Modal)
  166.                         PostMessage(wnd, ENDDIALOG, 0, 0);
  167.                     else
  168.                         SendMessage(wnd, CLOSE_WINDOW, TRUE, 0);
  169.                     return TRUE;
  170.                 case ID_HELP:
  171.                     if ((int)p2 != 0)
  172.                         return TRUE;
  173.                     return DisplayHelp(wnd, db->HelpName);
  174.                 default:
  175.                     break;
  176.             }
  177.             break;
  178.         case CLOSE_WINDOW:
  179.             if (!p1)    {
  180.                 SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  181.                 return TRUE;
  182.             }
  183.             break;
  184.         default:
  185.             break;
  186.     }
  187.     return BaseWndProc(DIALOG, wnd, msg, p1, p2);
  188. }
  189.  
  190. int DialogBox(WINDOW wnd, DBOX *db, int Modal,
  191.     int (*wndproc)(struct window *, enum messages, PARAM, PARAM))
  192. {
  193.     int rtn;
  194.     CTLWINDOW *ct;
  195.     WINDOW oldFocus = inFocus;
  196.     WINDOW DialogWnd = CreateWindow(DIALOG,
  197.                         db->dwnd.title,
  198.                         db->dwnd.x,
  199.                         db->dwnd.y,
  200.                         db->dwnd.h,
  201.                         db->dwnd.w,
  202.                         db,
  203.                         wnd,
  204.                         wndproc,
  205.                         Modal ? SAVESELF : 0);
  206.     DialogWnd->Modal = Modal;
  207.     SendMessage(((CTLWINDOW *)(DialogWnd->dFocus))->wnd, SETFOCUS, TRUE, 0);
  208.     SendMessage(DialogWnd, SHOW_WINDOW, 0, 0);
  209.     SendMessage(DialogWnd, INITIATE_DIALOG, 0, 0);
  210.     if (Modal)    {
  211.         SendMessage(DialogWnd, CAPTURE_MOUSE, 0, 0);
  212.         SendMessage(DialogWnd, CAPTURE_KEYBOARD, 0, 0);
  213.         while (dispatch_message())
  214.             ;
  215.         rtn = DialogWnd->ReturnCode == ID_OK;
  216.         SendMessage(DialogWnd, RELEASE_MOUSE, 0, 0);
  217.         SendMessage(DialogWnd, RELEASE_KEYBOARD, 0, 0);
  218.         SendMessage(inFocus, SETFOCUS, FALSE, 0);
  219.         SendMessage(DialogWnd, CLOSE_WINDOW, TRUE, 0);
  220.         SendMessage(oldFocus, SETFOCUS, TRUE, 0);
  221.         if (rtn)    {
  222.             ct = db->ctl;
  223.             while (ct->class)    {
  224.                 ct->wnd = NULL;
  225.                 if (ct->class == RADIOBUTTON || ct->class == CHECKBOX)
  226.                     ct->isetting = ct->setting;
  227.                 ct++;
  228.             }
  229.         }
  230.         return rtn;
  231.     }
  232.     return FALSE;
  233. }
  234.  
  235. static int inFocusCommand(DBOX *db)
  236. {
  237.     CTLWINDOW *ct = db->ctl;
  238.     while (ct->class)    {
  239.         if (ct->wnd == inFocus)
  240.             return ct->command;
  241.         ct++;
  242.     }
  243.     return -1;
  244. }
  245.  
  246. CTLWINDOW *FindCommand(DBOX *db, enum commands cmd, int class)
  247. {
  248.     CTLWINDOW *ct = db->ctl;
  249.     while (ct->class)    {
  250.         if (ct->class == class)
  251.             if (cmd == ct->command)
  252.                 return ct;
  253.         ct++;
  254.     }
  255.     return NULL;
  256. }
  257.  
  258. WINDOW ControlWindow(DBOX *db, enum commands cmd)
  259. {
  260.     CTLWINDOW *ct = db->ctl;
  261.     while (ct->class)    {
  262.         if (ct->class != TEXT && cmd == ct->command)
  263.             return ct->wnd;
  264.         ct++;
  265.     }
  266.     return NULL;
  267. }
  268.  
  269. void PushRadioButton(DBOX *db, enum commands cmd)
  270. {
  271.     CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON);
  272.     if (ct != NULL)    {
  273.         SetRadioButton(db, ct);
  274.         ct->isetting = ON;
  275.     }
  276. }
  277.  
  278. static struct {
  279.     CTLWINDOW *rct;
  280. } rbs[MAXRADIOS];
  281.  
  282. static void SetRadioButton(DBOX *db, CTLWINDOW *ct)
  283. {
  284.     CTLWINDOW *ctt = db->ctl;
  285.     int i;
  286.  
  287.     /* --- clear all the radio buttons
  288.                 in this group on the dialog box --- */
  289.  
  290.     /* -------- build a table of all radio buttons at the
  291.             same x vector ---------- */
  292.     for (i = 0; i < MAXRADIOS; i++)
  293.         rbs[i].rct = NULL;
  294.     while (ctt->class)    {
  295.         if (ctt->class == RADIOBUTTON)
  296.             if (ct->dwnd.x == ctt->dwnd.x)
  297.                 rbs[ctt->dwnd.y].rct = ctt;
  298.         ctt++;
  299.     }
  300.  
  301.     /* ----- find the start of the radiobutton group ---- */
  302.     i = ct->dwnd.y;
  303.     while (i >= 0 && rbs[i].rct != NULL)
  304.         --i;
  305.     /* ---- ignore everthing before the group ------ */
  306.     while (i >= 0)
  307.         rbs[i--].rct = NULL;
  308.  
  309.     /* ----- find the end of the radiobutton group ---- */
  310.     i = ct->dwnd.y;
  311.     while (i < MAXRADIOS && rbs[i].rct != NULL)
  312.         i++;
  313.     /* ---- ignore everthing past the group ------ */
  314.     while (i < MAXRADIOS)
  315.         rbs[i++].rct = NULL;
  316.  
  317.     for (i = 0; i < MAXRADIOS; i++)    {
  318.         if (rbs[i].rct != NULL)    {
  319.             int wason = rbs[i].rct->setting;
  320.             rbs[i].rct->setting = OFF;
  321.             if (wason)
  322.                 SendMessage(rbs[i].rct->wnd, PAINT, 0, 0);
  323.         }
  324.     }
  325.     ct->setting = ON;
  326.     SendMessage(ct->wnd, PAINT, 0, 0);
  327. }
  328.  
  329. int RadioButtonSetting(DBOX *db, enum commands cmd)
  330. {
  331.     CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON);
  332.     if (ct != NULL)
  333.         return (ct->setting == ON);
  334.     return FALSE;
  335. }
  336.  
  337. static void ControlSetting(DBOX *db, enum commands cmd,
  338.                                     int class, int setting)
  339. {
  340.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  341.     if (ct != NULL)
  342.         ct->isetting = setting;
  343. }
  344.  
  345. void SetCheckBox(DBOX *db, enum commands cmd)
  346. {
  347.     ControlSetting(db, cmd, CHECKBOX, ON);
  348. }
  349.  
  350. void ClearCheckBox(DBOX *db, enum commands cmd)
  351. {
  352.     ControlSetting(db, cmd, CHECKBOX, OFF);
  353. }
  354.  
  355. void EnableButton(DBOX *db, enum commands cmd)
  356. {
  357.     ControlSetting(db, cmd, BUTTON, ON);
  358. }
  359.  
  360. void DisableButton(DBOX *db, enum commands cmd)
  361. {
  362.     ControlSetting(db, cmd, BUTTON, OFF);
  363. }
  364.  
  365. int CheckBoxSetting(DBOX *db, enum commands cmd)
  366. {
  367.     CTLWINDOW *ct = FindCommand(db, cmd, CHECKBOX);
  368.     if (ct != NULL)
  369.         return (ct->isetting == ON);
  370.     return FALSE;
  371. }
  372.  
  373. char *GetDlgTextString(DBOX *db, enum commands cmd, CLASS class)
  374. {
  375.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  376.     if (ct != NULL)
  377.         return ct->itext;
  378.     else
  379.         return NULL;
  380. }
  381.  
  382. void SetDlgTextString(DBOX *db, enum commands cmd, char *text, CLASS class)
  383. {
  384.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  385.     if (ct != NULL)    {
  386.         ct->itext = realloc(ct->itext, strlen(text)+1);
  387.         if (ct->itext != NULL)
  388.             strcpy(ct->itext, text);
  389.     }
  390. }
  391.  
  392. static void Scrollers(WINDOW wnd)
  393. {
  394.     if (wnd->wlines > ClientHeight(wnd) &&
  395.             !TestAttribute(wnd, VSCROLLBAR))    {
  396.         AddAttribute(wnd, VSCROLLBAR);
  397.         SendMessage(wnd, BORDER, 0, 0);
  398.     }
  399. }
  400.  
  401. void PutComboListText(WINDOW wnd, enum commands cmd, char *text)
  402. {
  403.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  404.     if (ct != NULL)        {
  405.         WINDOW lwnd = ((WINDOW)(ct->wnd))->extension;
  406.         SendMessage(lwnd, ADDTEXT, (PARAM) text, 0);
  407.         Scrollers(lwnd);
  408.     }
  409. }
  410.  
  411. void PutItemText(WINDOW wnd, enum commands cmd, char *text)
  412. {
  413.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  414.  
  415.     if (ct == NULL)
  416.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  417.     if (ct == NULL)
  418.         ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  419.     if (ct == NULL)
  420.         ct = FindCommand(wnd->extension, cmd, LISTBOX);
  421.     if (ct == NULL)
  422.         ct = FindCommand(wnd->extension, cmd, SPINBUTTON);
  423.     if (ct == NULL)
  424.         ct = FindCommand(wnd->extension, cmd, TEXT);
  425.     if (ct != NULL)        {
  426.         WINDOW cwnd = (WINDOW) (ct->wnd);
  427.         switch (ct->class)    {
  428.             case COMBOBOX:
  429.             case EDITBOX:
  430.                 SendMessage(cwnd, EB_PUTTEXT, (PARAM) text, 0);
  431.                 if (!isMultiLine(cwnd))
  432.                     SendMessage(cwnd, PAINT, 0, 0);
  433.                 Scrollers(cwnd);
  434.                 break;
  435.             case LISTBOX:
  436.             case TEXTBOX:
  437.             case SPINBUTTON:
  438.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  439.                 Scrollers(cwnd);
  440.                 break;
  441.             case TEXT:    {
  442.                 SendMessage(cwnd, CLEARTEXT, 0, 0);
  443.                 SendMessage(cwnd, ADDTEXT, (PARAM) text, 0);
  444.                 SendMessage(cwnd, PAINT, 0, 0);
  445.                 break;
  446.             }
  447.             default:
  448.                 break;
  449.         }
  450.     }
  451. }
  452.  
  453. void GetItemText(WINDOW wnd, enum commands cmd, char *text, int len)
  454. {
  455.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  456.  
  457.     if (ct == NULL)
  458.         ct = FindCommand(wnd->extension, cmd, COMBOBOX);
  459.     if (ct == NULL)
  460.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  461.     if (ct == NULL)
  462.         ct = FindCommand(wnd->extension, cmd, TEXT);
  463.     if (ct != NULL)    {
  464.         WINDOW cwnd = (WINDOW) (ct->wnd);
  465.         if (cwnd != NULL)    {
  466.             switch (ct->class)    {
  467.                 case TEXT:
  468.                     if (GetText(cwnd) != NULL)    {
  469.                         unsigned char *cp = strchr(GetText(cwnd), '\n');
  470.                         if (cp != NULL)
  471.                             len = (int) (cp - GetText(cwnd));
  472.                         strncpy(text, GetText(cwnd), len);
  473.                         *(text+len) = '\0';
  474.                     }
  475.                     break;
  476.                 case TEXTBOX:
  477.                     if (GetText(cwnd) != NULL)
  478.                         strncpy(text, GetText(cwnd), len);
  479.                     break;
  480.                 case COMBOBOX:
  481.                 case EDITBOX:
  482.                     SendMessage(cwnd, EB_GETTEXT, (PARAM) text, len);
  483.                     break;
  484.                 default:
  485.                     break;
  486.             }
  487.         }
  488.     }
  489. }
  490.  
  491. void GetDlgListText(WINDOW wnd, char *text, enum commands cmd)
  492. {
  493.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, LISTBOX);
  494.     int sel = SendMessage(ct->wnd, LB_CURRENTSELECTION, 0, 0);
  495.     SendMessage(ct->wnd, LB_GETTEXT, (PARAM) text, sel);
  496. }
  497.  
  498. static int dircmp(const void *c1, const void *c2)
  499. {
  500.     return stricmp(*(char **)c1, *(char **)c2);
  501. }
  502.  
  503. int DlgDirList(WINDOW wnd, char *fspec,
  504.                 enum commands nameid, enum commands pathid,
  505.                 unsigned attrib)
  506. {
  507.     int ax, i = 0, criterr = 1;
  508.     struct ffblk ff;
  509.     CTLWINDOW *ct = FindCommand(wnd->extension, nameid, LISTBOX);
  510.     WINDOW lwnd;
  511.     char **dirlist = NULL;
  512.  
  513.     CreatePath(path, fspec, TRUE, TRUE);
  514.  
  515.     if (ct != NULL)    {
  516.         lwnd = ct->wnd;
  517.         SendMessage(ct->wnd, CLEARTEXT, 0, 0);
  518.  
  519.         if (attrib & 0x8000)    {
  520.             union REGS regs;
  521.             char drname[15];
  522.             unsigned int cd, dr;
  523.  
  524.             cd = getdisk();
  525.             for (dr = 0; dr < 26; dr++)    {
  526.                 unsigned ndr;
  527.                 setdisk(dr);
  528.                 ndr = getdisk();
  529.                 if (ndr == dr)    {
  530.                     /* ------- test for remapped B drive ------- */
  531.                     if (dr == 1)    {
  532.                         regs.x.ax = 0x440e;        /* IOCTL function 14 */
  533.                         regs.h.bl = dr+1;
  534.                         int86(DOS, ®s, ®s);
  535.                         if (regs.h.al != 0)
  536.                             continue;
  537.                     }
  538.  
  539.                     sprintf(drname, "[%c:]", dr+'A');
  540.  
  541.                     /* ------ test for network or RAM disk ---- */
  542.                     regs.x.ax = 0x4409;        /* IOCTL function 9 */
  543.                     regs.h.bl = dr+1;
  544.                     int86(DOS, ®s, ®s);
  545.                     if (!regs.x.cflag)    {
  546.                         if (regs.x.dx & 0x1000)
  547.                             strcat(drname, " (Network)");
  548.                         else if (regs.x.dx == 0x0800)
  549.                             strcat(drname, " (RAMdisk)");
  550.                     }
  551.                     SendMessage(lwnd, ADDTEXT, (PARAM) drname, 0);
  552.                 }
  553.             }
  554.             setdisk(cd);
  555.         }
  556.  
  557.         while (criterr == 1)    {
  558.             ax = findfirst(path, &ff, attrib & 0x3f);
  559.             criterr = TestCriticalError();
  560.         }
  561.         if (criterr)
  562.             return FALSE;
  563.         while (ax == 0)    {
  564.             if (!((attrib & 0x4000) &&
  565.                     (ff.ff_attrib & (attrib & 0x3f)) == 0) &&
  566.                         strcmp(ff.ff_name, "."))    {
  567.                 char fname[15];
  568.                 sprintf(fname, (ff.ff_attrib & 0x10) ?
  569.                                 "[%s]" : "%s" , ff.ff_name);
  570.                 dirlist = realloc(dirlist, sizeof(char *)*(i+1));
  571.                 if (dirlist != NULL)    {
  572.                     dirlist[i] = malloc(strlen(fname)+1);
  573.                     if (dirlist[i] != NULL)
  574.                         strcpy(dirlist[i], fname);
  575.                     i++;
  576.                 }
  577.             }
  578.             ax = findnext(&ff);
  579.         }
  580.         if (dirlist != NULL)    {
  581.             int j;
  582.             /* -- sort file/drive/directory list box data -- */
  583.             qsort(dirlist, i, sizeof(void *), dircmp);
  584.  
  585.             /* ---- send sorted list to list box ---- */
  586.             for (j = 0; j < i; j++)    {
  587.                 SendMessage(lwnd, ADDTEXT, (PARAM) dirlist[j], 0);
  588.                 free(dirlist[j]);
  589.             }
  590.             free(dirlist);
  591.         }
  592.         if (lwnd->wlines > ClientHeight(lwnd))
  593.             AddAttribute(lwnd, VSCROLLBAR);
  594.         else
  595.             ClearAttribute(lwnd, VSCROLLBAR);
  596.         SendMessage(lwnd, SHOW_WINDOW, 0, 0);
  597.     }
  598.  
  599.     if (pathid)    {
  600.         fnmerge(path, drive, dir, NULL, NULL);
  601.         PutItemText(wnd, pathid, path);
  602.     }
  603.  
  604.     return TRUE;
  605. }
  606.  
  607. static CTLWINDOW *AssociatedControl(DBOX *db, enum commands Tcmd)
  608. {
  609.     CTLWINDOW *ct = db->ctl;
  610.     while (ct->class)    {
  611.         if (ct->class != TEXT)
  612.             if (ct->command == Tcmd)
  613.                 break;
  614.         ct++;
  615.     }
  616.     return ct;
  617. }
  618.  
  619. static void dbShortcutKeys(DBOX *db, int ky)
  620. {
  621.     CTLWINDOW *ct;
  622.     int ch = AltConvert(ky);
  623.  
  624.     if (ch != 0)    {
  625.         ct = db->ctl;
  626.         while (ct->class)    {
  627.             char *cp = ct->vtext;
  628.             while (cp && *cp)    {
  629.                 if (*cp == SHORTCUTCHAR && tolower(*(cp+1)) == ch)    {
  630.                     if (ct->class == TEXT)
  631.                         ct = AssociatedControl(db, ct->command);
  632.                     if (ct->class == RADIOBUTTON)
  633.                         SetRadioButton(db, ct);
  634.                     else if (ct->class == CHECKBOX)    {
  635.                         ct->setting ^= ON;
  636.                         SendMessage(ct->wnd, PAINT, 0, 0);
  637.                     }
  638.                     else if (ct->class)    {
  639.                         SendMessage(ct->wnd, SETFOCUS, TRUE, 0);
  640.                         if (ct->class == BUTTON)
  641.                             SendMessage(ct->wnd, KEYBOARD, '\r', 0);
  642.                     }
  643.                     return;
  644.                 }
  645.                 cp++;
  646.             }
  647.             ct++;
  648.         }
  649.     }
  650. }
  651.  
  652. /* generic window processor used by all dialog box control windows */
  653. static int ControlProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  654. {
  655.     DBOX *db;
  656.     CTLWINDOW *ct;
  657.  
  658.     if (wnd == NULL)
  659.         return FALSE;
  660.     db = GetParent(wnd) ? GetParent(wnd)->extension : NULL;
  661.     ct = GetControl(wnd);
  662.  
  663.     switch (msg)    {
  664.         case CREATE_WINDOW:
  665.             ct = wnd->ct = wnd->extension;
  666.             wnd->extension = NULL;
  667.             if (ct != NULL)
  668.                 ct->wnd = wnd;
  669.             break;
  670.         case KEYBOARD:
  671.             switch ((int) p1)    {
  672.                 case F1:
  673.                     if (WindowMoving || WindowSizing)
  674.                         break;
  675.                     if (!DisplayHelp(wnd, ct->help))
  676.                         SendMessage(GetParent(wnd), COMMAND, ID_HELP, 0);
  677.                     return TRUE;
  678.                 case ' ':
  679.                     if (!((int)p2 & ALTKEY))
  680.                         break;
  681.                 case ALT_F6:
  682.                 case CTRL_F4:
  683.                 case ALT_F4:
  684.                     PostMessage(GetParent(wnd), msg, p1, p2);
  685.                     return TRUE;
  686.                 default:
  687.                     break;
  688.             }
  689.             if (GetClass(wnd) == EDITBOX)
  690.                 if (isMultiLine(wnd))
  691.                     break;
  692.             switch ((int) p1)    {
  693.                 case UP:
  694.                     if (!isDerivedFrom(wnd, LISTBOX))    {
  695.                         p1 = CTRL_FIVE;
  696.                         p2 = LEFTSHIFT;
  697.                     }
  698.                     break;
  699.                 case BS:
  700.                     if (!isDerivedFrom(wnd, EDITBOX))    {
  701.                         p1 = CTRL_FIVE;
  702.                         p2 = LEFTSHIFT;
  703.                     }
  704.                     break;
  705.                 case DN:
  706.                     if (!isDerivedFrom(wnd, LISTBOX) &&
  707.                             !isDerivedFrom(wnd, COMBOBOX))
  708.                         p1 = '\t';
  709.                     break;
  710.                 case FWD:
  711.                     if (!isDerivedFrom(wnd, EDITBOX))
  712.                         p1 = '\t';
  713.                     break;
  714.                 case '\r':
  715.                     if (isDerivedFrom(wnd, EDITBOX))
  716.                         if (isMultiLine(wnd))
  717.                             break;
  718.                     if (isDerivedFrom(wnd, BUTTON))
  719.                         break;
  720.                     SendMessage(GetParent(wnd), COMMAND, ID_OK, 0);
  721.                     return TRUE;
  722.                 default:
  723.                     break;
  724.             }
  725.             break;
  726.         case SETFOCUS:
  727.             if (p1)    {
  728.                 DefaultWndProc(wnd, msg, p1, p2);
  729.                 GetParent(wnd)->dFocus = ct;
  730.                 SendMessage(GetParent(wnd), COMMAND,
  731.                     inFocusCommand(db), ENTERFOCUS);
  732.                 return TRUE;
  733.             }
  734.             else 
  735.                 SendMessage(GetParent(wnd), COMMAND,
  736.                     inFocusCommand(db), LEAVEFOCUS);
  737.             break;
  738.         case CLOSE_WINDOW:
  739.             if (ct != NULL)
  740.                 if (GetParent(wnd)->ReturnCode == ID_OK &&
  741.                         (ct->class == EDITBOX || ct->class == COMBOBOX))
  742.                     if (wnd->TextChanged)
  743.                         if ((ct->itext = realloc(ct->itext,    strlen(wnd->text)+1)) != NULL)    {
  744.                             strcpy(ct->itext, wnd->text);
  745.                             if (!isMultiLine(wnd))    {
  746.                                 char *cp = ct->itext+strlen(ct->itext)-1;
  747.                                 if (*cp == '\n')
  748.                                     *cp = '\0';
  749.                             }
  750.                         }
  751.             break;
  752.         default:
  753.             break;
  754.     }
  755.     return DefaultWndProc(wnd, msg, p1, p2);
  756. }
  757.  
  758. /* ----- Create unambiguous path from file spec, filling in the
  759.      drive and directory if incomplete. Optionally change to
  760.      the new drive and subdirectory ------ */
  761. void CreatePath(char *path, char *fspec, int InclName, int Change)
  762. {
  763.     int cm = 0;
  764.     unsigned currdrive;
  765.     char currdir[64];
  766.     char *cp;
  767.  
  768.     if (!Change)    {
  769.         /* ----- save the current drive and subdirectory ----- */
  770.         currdrive = getdisk();
  771.         getcwd(currdir, sizeof currdir);
  772.         memmove(currdir, currdir+2, strlen(currdir+1));
  773.         cp = currdir+strlen(currdir)-1;
  774.         if (*cp == '\\')
  775.             *cp = '\0';
  776.     }
  777.  
  778.     *drive = *dir = *name = *ext = '\0';
  779.     fnsplit(fspec, drive, dir, name, ext);
  780.     if (!InclName)
  781.         *name = *ext = '\0';
  782.     *drive = toupper(*drive);
  783.  
  784.     if (*ext)
  785.         cm |= EXTENSION;
  786.     if (InclName && *name)
  787.         cm |= FILENAME;
  788.     if (*dir)
  789.         cm |= DIRECTORY;
  790.     if (*drive)
  791.         cm |= DRIVE;
  792.  
  793.     if (cm & DRIVE)
  794.         setdisk(*drive - 'A');
  795.     else     {
  796.         *drive = getdisk();
  797.         *drive += 'A';
  798.     }
  799.  
  800.     if (cm & DIRECTORY)    {
  801.         cp = dir+strlen(dir)-1;
  802.         if (*cp == '\\')
  803.             *cp = '\0';
  804.         chdir(dir);
  805.     }
  806.     getcwd(dir, sizeof dir);
  807.     memmove(dir, dir+2, strlen(dir+1));
  808.  
  809.     if (InclName)    {
  810.         if (!(cm & FILENAME))
  811.             strcpy(name, "*");
  812.         if (!(cm & EXTENSION))
  813.             strcpy(ext, ".*");
  814.     }
  815.     else
  816.         *name = *ext = '\0';
  817.     if (dir[strlen(dir)-1] != '\\')
  818.         strcat(dir, "\\");
  819.     memset(path, 0, sizeof path);
  820.     fnmerge(path, drive, dir, name, ext);
  821.  
  822.     if (!Change)    {
  823.         setdisk(currdrive);
  824.         chdir(currdir);
  825.     }
  826. }
  827.  
  828. static void ChangeFocus(WINDOW wnd, int direc)
  829. {
  830.     DBOX *db = wnd->extension;
  831.      CTLWINDOW *ct = db->ctl;
  832.      CTLWINDOW *ctt;
  833.  
  834.     /* --- find the control that has the focus --- */
  835.     while (ct->class)    {
  836.         if (ct == wnd->dFocus)
  837.             break;
  838.         ct++;
  839.     }
  840.     if (ct->class)    {
  841.         ctt = ct;
  842.         do    {
  843.             /* ----- point to next or previous control ----- */
  844.             if (direc)    {
  845.                 ct++;
  846.                 if (ct->class == 0)
  847.                     ct = db->ctl;
  848.             }
  849.             else    {
  850.                 if (ct == db->ctl)
  851.                     while (ct->class)
  852.                         ct++;
  853.                 --ct;
  854.             }
  855.  
  856.             if (ct->class != BOX && ct->class != TEXT)    {
  857.                 SendMessage(ct->wnd, SETFOCUS, TRUE, 0);
  858.                 SendMessage(ctt->wnd, PAINT, 0, 0);
  859.                 SendMessage(ct->wnd, PAINT, 0, 0);
  860.                 break;
  861.             }
  862.         } while (ct != ctt);
  863.     }
  864. }
  865.